package cn.community.system.config;


import cn.community.system.shiro.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.authz.ModularRealmAuthorizer;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import javax.servlet.Filter;
import java.util.*;

@Configuration
public class ShiroConfig {

    /**
     *  开启Shiro的注解
     * @return
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        advisorAutoProxyCreator.setUsePrefix(true);
        return advisorAutoProxyCreator;
    }

    // FreeMarker提供shiro标签
    @Bean
    public FreeMarkerConfigurer freeMarkerConfigurer() {
        MyFreeMarkerConfig myFreeMarkerConfig = new MyFreeMarkerConfig();
        myFreeMarkerConfig.setTemplateLoaderPath("classpath:templates/");
        return myFreeMarkerConfig;
    }


    /**
     * 安全管理器
     * @param adminRealm
     * @param associationRealm
     * @param cacheManager
     * @return
     */
    @Bean
    public DefaultWebSecurityManager securityManager(AdminRealm adminRealm, AssociationRealm associationRealm, MemberRealm memberRealm, CacheManager cacheManager){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 添加realms
        List<Realm> realms = new ArrayList<>();
        realms.add(adminRealm);
        realms.add(associationRealm);
        realms.add(memberRealm);
        // 设置realm(需要定义在realm之前)  认证控制
        securityManager.setAuthenticator(modularRealmAuthenticator());
        // 新增授权控制
        securityManager.setAuthorizer(modularRealmAuthorizer());
        securityManager.setRealms(realms);  //关联自定义Realm
        securityManager.setCacheManager(cacheManager);//缓存管理器
        return securityManager;
    }

    // 重要！！！定义token与Realm关系，配置认证策略（系统自带的Realm管理，主要针对多realm 认证）
    @Bean
    public ModularRealmAuthenticator modularRealmAuthenticator(){
        // 自己重写的ModularRealmAuthenticator
        UserModularReamAuthenticator authenticator = new UserModularReamAuthenticator();
        authenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
        return authenticator;
    }

    // 重要！！！系统自带的Realm管理，主要针对多realm 授权
    @Bean
    public ModularRealmAuthorizer modularRealmAuthorizer(){
        // 自己重写的ModularRealmAuthorizer
        UserModularReamAuthorizer authorizer = new UserModularReamAuthorizer();
        return authorizer;
    }

    /**
     * shiro过滤器
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean  = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String, Filter> filters = new LinkedHashMap<>();
        //自定义过滤器
        filters.put("authc", new AjaxFormAuthenticationFilter());
        shiroFilterFactoryBean.setFilters(filters);
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();
        filterChainDefinitionMap.put("/logout.do", "logout");
        filterChainDefinitionMap.put("/css/**", "anon");  // 登录相关不拦截
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/profile/**", "anon");
        filterChainDefinitionMap.put("/uploadImg.do", "anon");
        filterChainDefinitionMap.put("/regist.html", "anon");
        filterChainDefinitionMap.put("/users/associationRegist.do", "anon");
        filterChainDefinitionMap.put("/users/memberRegist.do", "anon");
        filterChainDefinitionMap.put("/users/randomCode.do", "anon");
        filterChainDefinitionMap.put("/users/adminLogin.do", "anon");
        filterChainDefinitionMap.put("/users/associationLogin.do", "anon");
        filterChainDefinitionMap.put("/users/memberLogin.do", "anon");
        filterChainDefinitionMap.put("/**", "authc");  // 需要认证拦截
        shiroFilterFactoryBean.setLoginUrl("/login.html");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    /**
     * 密码匹配器
     * @return
     */
    @Bean
    public CredentialsMatcher credentialsMatcher(){
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("md5");
        return credentialsMatcher;
    }

    /**
     * 缓存管理器
     * @return
     */
    @Bean
    protected CacheManager cacheManager() {
        return new MemoryConstrainedCacheManager();
    }

}